"""
PPT生成器
使用python-pptx库实现PPT文件的创建和生成功能。
"""

import os
import logging
from typing import Dict, List, Optional, Any, Tuple
from datetime import datetime
from pathlib import Path

from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR
from pptx.enum.shapes import MSO_SHAPE
from pptx.dml.color import RGBColor
from pptx.enum.dml import MSO_THEME_COLOR

from ..models import SlideContent, SlideType, TemplateConfig
from ..services.template_manager import template_manager
from .style_applicator import style_applicator

logger = logging.getLogger(__name__)


class PPTGenerator:
    """
    PPT生成器类
    
    负责使用python-pptx库创建和生成PowerPoint演示文稿
    """
    
    def __init__(self, output_dir: str = None):
        """
        初始化PPT生成器
        
        Args:
            output_dir: 输出目录路径
        """
        self.output_dir = output_dir or os.path.join("backend", "temp")
        
        # 确保输出目录存在
        Path(self.output_dir).mkdir(parents=True, exist_ok=True)
        
        # 幻灯片尺寸配置（16:9比例）
        self.slide_width = Inches(13.33)
        self.slide_height = Inches(7.5)
        
        # 默认字体配置
        self.default_fonts = {
            "title": {"name": "Microsoft YaHei", "size": Pt(32)},
            "heading": {"name": "Microsoft YaHei", "size": Pt(24)},
            "body": {"name": "Microsoft YaHei", "size": Pt(16)},
            "caption": {"name": "Microsoft YaHei", "size": Pt(12)}
        }
    
    def create_presentation(
        self,
        slides: List[SlideContent],
        template_id: str = "professional",
        title: str = "AI生成的演示文稿"
    ) -> str:
        """
        创建完整的PPT演示文稿
        
        Args:
            slides: 幻灯片内容列表
            template_id: 模板ID
            title: 演示文稿标题
            
        Returns:
            str: 生成的PPT文件路径
        """
        try:
            logger.info(f"开始创建PPT演示文稿 - 标题: {title}, 幻灯片数量: {len(slides)}")
            
            # 创建新的演示文稿
            prs = Presentation()
            
            # 设置幻灯片尺寸
            prs.slide_width = self.slide_width
            prs.slide_height = self.slide_height
            
            # 获取模板配置
            template_config = template_manager.get_template(template_id)
            if not template_config:
                logger.warning(f"模板不存在，使用默认模板: {template_id}")
                template_config = template_manager.get_template("professional")
            
            # 为每个幻灯片内容创建幻灯片
            for i, slide_content in enumerate(slides):
                try:
                    self._create_slide(prs, slide_content, template_config, i + 1)
                    logger.debug(f"创建幻灯片成功: {slide_content.title}")
                except Exception as e:
                    logger.error(f"创建幻灯片失败 {slide_content.title}: {e}")
                    continue
            
            # 生成文件名和路径
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"presentation_{timestamp}.pptx"
            file_path = os.path.join(self.output_dir, filename)
            
            # 保存演示文稿
            prs.save(file_path)
            
            logger.info(f"PPT演示文稿创建成功: {file_path}")
            return file_path
            
        except Exception as e:
            logger.error(f"创建PPT演示文稿失败: {e}")
            raise Exception(f"创建PPT演示文稿失败: {str(e)}")
    
    def _create_slide(
        self,
        prs: Presentation,
        slide_content: SlideContent,
        template_config: TemplateConfig,
        slide_number: int
    ):
        """
        创建单个幻灯片
        
        Args:
            prs: 演示文稿对象
            slide_content: 幻灯片内容
            template_config: 模板配置
            slide_number: 幻灯片编号
        """
        # 根据幻灯片类型选择布局
        layout_index = self._get_layout_index(slide_content.slide_type)
        slide_layout = prs.slide_layouts[layout_index]
        
        # 添加幻灯片
        slide = prs.slides.add_slide(slide_layout)
        
        # 应用幻灯片整体样式
        slide_type_key = self._get_slide_type_key(slide_content.slide_type)
        style_applicator.apply_slide_style(slide, template_config, slide_type_key)
        
        # 根据幻灯片类型添加内容
        if slide_content.slide_type == SlideType.TITLE:
            self._create_title_slide_enhanced(slide, slide_content, template_config)
        elif slide_content.slide_type == SlideType.CONTENT:
            self._create_content_slide_enhanced(slide, slide_content, template_config)
        elif slide_content.slide_type == SlideType.IMAGE:
            self._create_image_slide_enhanced(slide, slide_content, template_config)
        elif slide_content.slide_type == SlideType.CHART:
            self._create_chart_slide_enhanced(slide, slide_content, template_config)
        elif slide_content.slide_type == SlideType.CONCLUSION:
            self._create_conclusion_slide_enhanced(slide, slide_content, template_config)
        else:
            # 默认使用内容幻灯片布局
            self._create_content_slide_enhanced(slide, slide_content, template_config)
        
        # 应用布局和间距控制
        layout_config = template_config.style.layouts.get(slide_type_key)
        if layout_config:
            style_applicator.apply_layout_spacing(slide, layout_config, template_config)
        
        # 检查样式一致性
        consistency_report = style_applicator.check_style_consistency(slide, template_config)
        if not consistency_report["consistent"]:
            logger.debug(f"幻灯片样式一致性问题: {consistency_report['issues']}")
    
    def _get_layout_index(self, slide_type: SlideType) -> int:
        """
        根据幻灯片类型获取布局索引
        
        Args:
            slide_type: 幻灯片类型
            
        Returns:
            int: 布局索引
        """
        layout_mapping = {
            SlideType.TITLE: 0,  # 标题幻灯片
            SlideType.CONTENT: 1,  # 标题和内容
            SlideType.SECTION_HEADER: 2,  # 节标题
            SlideType.BULLET_POINTS: 1,  # 项目符号（使用标题和内容布局）
            SlideType.COMPARISON: 3,  # 比较（使用两栏布局）
            SlideType.IMAGE: 6,  # 标题和图片
            SlideType.CHART: 5,  # 标题和图表
            SlideType.CONCLUSION: 1,  # 结论（使用标题和内容布局）
        }
        
        return layout_mapping.get(slide_type, 1)  # 默认使用标题和内容布局
    
    def _set_slide_background(self, slide, template_config: TemplateConfig):
        """
        设置幻灯片背景
        
        Args:
            slide: 幻灯片对象
            template_config: 模板配置
        """
        try:
            # 获取背景颜色
            bg_color = template_config.style.color_scheme.background
            
            # 设置背景填充
            background = slide.background
            fill = background.fill
            fill.solid()
            
            # 解析十六进制颜色
            rgb_color = self._hex_to_rgb(bg_color)
            fill.fore_color.rgb = RGBColor(*rgb_color)
            
        except Exception as e:
            logger.warning(f"设置幻灯片背景失败: {e}")
    
    def _create_title_slide(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建标题幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 应用标题字体样式
                self._apply_font_style(
                    title_shape.text_frame,
                    template_config.style.fonts["title"],
                    template_config.style.color_scheme.primary
                )
            
            # 设置副标题（使用内容的第一项）
            if hasattr(slide.placeholders, 'placeholders') and len(slide.placeholders) > 1:
                if slide_content.content:
                    subtitle_placeholder = slide.placeholders[1]
                    subtitle_placeholder.text = slide_content.content[0] if slide_content.content else ""
                    
                    # 应用副标题字体样式
                    self._apply_font_style(
                        subtitle_placeholder.text_frame,
                        template_config.style.fonts["heading"],
                        template_config.style.color_scheme.text_secondary
                    )
            
        except Exception as e:
            logger.error(f"创建标题幻灯片失败: {e}")
    
    def _create_content_slide(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建内容幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 应用标题字体样式
                self._apply_font_style(
                    title_shape.text_frame,
                    template_config.style.fonts["heading"],
                    template_config.style.color_scheme.primary
                )
            
            # 设置内容
            if len(slide.placeholders) > 1:
                content_placeholder = slide.placeholders[1]
                
                # 清空现有内容
                content_placeholder.text = ""
                text_frame = content_placeholder.text_frame
                
                # 添加内容项
                for i, content_item in enumerate(slide_content.content):
                    if i == 0:
                        # 第一个段落使用现有的段落
                        p = text_frame.paragraphs[0]
                    else:
                        # 添加新段落
                        p = text_frame.add_paragraph()
                    
                    p.text = content_item
                    p.level = 0  # 设置为第一级项目符号
                    
                    # 应用正文字体样式
                    self._apply_paragraph_style(
                        p,
                        template_config.style.fonts["body"],
                        template_config.style.color_scheme.text_primary
                    )
            
        except Exception as e:
            logger.error(f"创建内容幻灯片失败: {e}")
    
    def _create_image_slide(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建图片幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 应用标题字体样式
                self._apply_font_style(
                    title_shape.text_frame,
                    template_config.style.fonts["heading"],
                    template_config.style.color_scheme.primary
                )
            
            # 添加图片占位符文本框
            left = Inches(1)
            top = Inches(2)
            width = Inches(8)
            height = Inches(4)
            
            textbox = slide.shapes.add_textbox(left, top, width, height)
            text_frame = textbox.text_frame
            
            # 添加图片占位符文本
            placeholder_text = "图片占位符"
            if slide_content.visual_elements:
                placeholder_text = f"图片占位符: {', '.join(slide_content.visual_elements)}"
            
            p = text_frame.paragraphs[0]
            p.text = placeholder_text
            p.alignment = PP_ALIGN.CENTER
            
            # 应用字体样式
            self._apply_paragraph_style(
                p,
                template_config.style.fonts["body"],
                template_config.style.color_scheme.text_secondary
            )
            
            # 添加边框
            line = textbox.line
            line.color.rgb = RGBColor(*self._hex_to_rgb(template_config.style.color_scheme.border))
            line.width = Pt(1)
            
        except Exception as e:
            logger.error(f"创建图片幻灯片失败: {e}")
    
    def _create_chart_slide(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建图表幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 应用标题字体样式
                self._apply_font_style(
                    title_shape.text_frame,
                    template_config.style.fonts["heading"],
                    template_config.style.color_scheme.primary
                )
            
            # 添加图表占位符
            left = Inches(1)
            top = Inches(2)
            width = Inches(8)
            height = Inches(4)
            
            # 创建一个矩形作为图表占位符
            chart_placeholder = slide.shapes.add_shape(
                MSO_SHAPE.RECTANGLE, left, top, width, height
            )
            
            # 设置占位符样式
            fill = chart_placeholder.fill
            fill.solid()
            fill.fore_color.rgb = RGBColor(240, 240, 240)  # 浅灰色背景
            
            # 设置边框
            line = chart_placeholder.line
            line.color.rgb = RGBColor(*self._hex_to_rgb(template_config.style.color_scheme.border))
            line.width = Pt(2)
            
            # 添加图表说明文本
            textbox = slide.shapes.add_textbox(left, top + height + Inches(0.2), width, Inches(1))
            text_frame = textbox.text_frame
            
            chart_description = "图表占位符"
            if slide_content.content:
                chart_description = " | ".join(slide_content.content)
            
            p = text_frame.paragraphs[0]
            p.text = chart_description
            p.alignment = PP_ALIGN.CENTER
            
            # 应用字体样式
            self._apply_paragraph_style(
                p,
                template_config.style.fonts["caption"],
                template_config.style.color_scheme.text_secondary
            )
            
        except Exception as e:
            logger.error(f"创建图表幻灯片失败: {e}")
    
    def _create_conclusion_slide(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建结论幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 结论幻灯片使用与内容幻灯片相同的布局，但样式稍有不同
            self._create_content_slide(slide, slide_content, template_config)
            
            # 为结论幻灯片添加特殊的视觉效果（如果需要）
            # 这里可以添加额外的装饰元素
            
        except Exception as e:
            logger.error(f"创建结论幻灯片失败: {e}")
    
    def _apply_font_style(self, text_frame, font_config, color_hex: str):
        """
        应用字体样式到文本框
        
        Args:
            text_frame: 文本框对象
            font_config: 字体配置
            color_hex: 颜色十六进制值
        """
        try:
            for paragraph in text_frame.paragraphs:
                self._apply_paragraph_style(paragraph, font_config, color_hex)
        except Exception as e:
            logger.warning(f"应用字体样式失败: {e}")
    
    def _apply_paragraph_style(self, paragraph, font_config, color_hex: str):
        """
        应用字体样式到段落
        
        Args:
            paragraph: 段落对象
            font_config: 字体配置
            color_hex: 颜色十六进制值
        """
        try:
            for run in paragraph.runs:
                font = run.font
                font.name = font_config.family
                font.size = Pt(font_config.size)
                
                # 设置字体粗细
                if font_config.weight == "bold":
                    font.bold = True
                elif font_config.weight == "light":
                    font.bold = False
                
                # 设置字体颜色
                rgb_color = self._hex_to_rgb(color_hex)
                font.color.rgb = RGBColor(*rgb_color)
                
        except Exception as e:
            logger.warning(f"应用段落样式失败: {e}")
    
    def _hex_to_rgb(self, hex_color: str) -> Tuple[int, int, int]:
        """
        将十六进制颜色转换为RGB元组
        
        Args:
            hex_color: 十六进制颜色值（如 #FF0000）
            
        Returns:
            Tuple[int, int, int]: RGB颜色元组
        """
        try:
            hex_color = hex_color.lstrip('#')
            return tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
        except Exception:
            # 如果转换失败，返回黑色
            return (0, 0, 0)
    
    def get_slide_layouts_info(self) -> List[Dict[str, Any]]:
        """
        获取可用的幻灯片布局信息
        
        Returns:
            List[Dict]: 布局信息列表
        """
        try:
            prs = Presentation()
            layouts_info = []
            
            for i, layout in enumerate(prs.slide_layouts):
                layout_info = {
                    "index": i,
                    "name": layout.name,
                    "placeholders": []
                }
                
                for placeholder in layout.placeholders:
                    placeholder_info = {
                        "index": placeholder.placeholder_format.idx,
                        "type": placeholder.placeholder_format.type,
                        "name": placeholder.name
                    }
                    layout_info["placeholders"].append(placeholder_info)
                
                layouts_info.append(layout_info)
            
            return layouts_info
            
        except Exception as e:
            logger.error(f"获取幻灯片布局信息失败: {e}")
            return []
    
    def _get_slide_type_key(self, slide_type: SlideType) -> str:
        """
        获取幻灯片类型对应的配置键
        
        Args:
            slide_type: 幻灯片类型
            
        Returns:
            str: 配置键名
        """
        type_mapping = {
            SlideType.TITLE: "title_slide",
            SlideType.CONTENT: "content_slide",
            SlideType.IMAGE: "content_slide",
            SlideType.CHART: "content_slide",
            SlideType.CONCLUSION: "content_slide",
            SlideType.SECTION_HEADER: "content_slide",
            SlideType.BULLET_POINTS: "content_slide",
            SlideType.COMPARISON: "content_slide"
        }
        return type_mapping.get(slide_type, "content_slide")
    
    def _create_title_slide_enhanced(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建增强版标题幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 使用样式应用器应用标题样式
                style_applicator.apply_text_style(
                    title_shape.text_frame,
                    "title",
                    template_config
                )
            
            # 设置副标题（使用内容的第一项）
            if len(slide.placeholders) > 1 and slide_content.content:
                subtitle_placeholder = slide.placeholders[1]
                subtitle_placeholder.text = slide_content.content[0] if slide_content.content else ""
                
                # 应用副标题样式
                style_applicator.apply_text_style(
                    subtitle_placeholder.text_frame,
                    "heading",
                    template_config,
                    template_config.style.color_scheme.text_secondary
                )
            
        except Exception as e:
            logger.error(f"创建增强版标题幻灯片失败: {e}")
    
    def _create_content_slide_enhanced(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建增强版内容幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 使用样式应用器应用标题样式
                style_applicator.apply_text_style(
                    title_shape.text_frame,
                    "heading",
                    template_config
                )
            
            # 设置内容
            if len(slide.placeholders) > 1:
                content_placeholder = slide.placeholders[1]
                
                # 清空现有内容
                content_placeholder.text = ""
                text_frame = content_placeholder.text_frame
                
                # 添加内容项
                for i, content_item in enumerate(slide_content.content):
                    if i == 0:
                        # 第一个段落使用现有的段落
                        p = text_frame.paragraphs[0]
                    else:
                        # 添加新段落
                        p = text_frame.add_paragraph()
                    
                    p.text = content_item
                    p.level = 0  # 设置为第一级项目符号
                
                # 使用样式应用器应用正文样式
                style_applicator.apply_text_style(
                    text_frame,
                    "body",
                    template_config
                )
            
        except Exception as e:
            logger.error(f"创建增强版内容幻灯片失败: {e}")
    
    def _create_image_slide_enhanced(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建增强版图片幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 使用样式应用器应用标题样式
                style_applicator.apply_text_style(
                    title_shape.text_frame,
                    "heading",
                    template_config
                )
            
            # 创建带样式的图片占位符
            placeholder_text = "图片占位符"
            if slide_content.visual_elements:
                placeholder_text = f"图片: {', '.join(slide_content.visual_elements)}"
            
            image_placeholder = style_applicator.create_styled_image_placeholder(
                slide=slide,
                left=1.0,
                top=2.0,
                width=8.0,
                height=4.0,
                template_config=template_config,
                placeholder_text=placeholder_text
            )
            
            # 如果有内容描述，添加到幻灯片底部
            if slide_content.content:
                description_text = " | ".join(slide_content.content)
                textbox = slide.shapes.add_textbox(
                    Inches(1), Inches(6.5), Inches(8), Inches(0.8)
                )
                text_frame = textbox.text_frame
                p = text_frame.paragraphs[0]
                p.text = description_text
                p.alignment = PP_ALIGN.CENTER
                
                # 应用样式
                style_applicator.apply_text_style(
                    text_frame,
                    "caption",
                    template_config
                )
            
        except Exception as e:
            logger.error(f"创建增强版图片幻灯片失败: {e}")
    
    def _create_chart_slide_enhanced(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建增强版图表幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 设置标题
            if slide.shapes.title:
                title_shape = slide.shapes.title
                title_shape.text = slide_content.title
                
                # 使用样式应用器应用标题样式
                style_applicator.apply_text_style(
                    title_shape.text_frame,
                    "heading",
                    template_config
                )
            
            # 确定图表类型
            chart_type = "柱状图"
            if slide_content.visual_elements:
                for element in slide_content.visual_elements:
                    if "图" in element:
                        chart_type = element
                        break
            
            # 创建带样式的图表占位符
            chart_placeholder = style_applicator.create_styled_chart_placeholder(
                slide=slide,
                left=1.0,
                top=2.0,
                width=8.0,
                height=4.0,
                template_config=template_config,
                chart_type=chart_type
            )
            
            # 添加数据说明
            if slide_content.content:
                data_text = " | ".join(slide_content.content)
                textbox = slide.shapes.add_textbox(
                    Inches(1), Inches(6.5), Inches(8), Inches(0.8)
                )
                text_frame = textbox.text_frame
                p = text_frame.paragraphs[0]
                p.text = f"数据: {data_text}"
                p.alignment = PP_ALIGN.CENTER
                
                # 应用样式
                style_applicator.apply_text_style(
                    text_frame,
                    "caption",
                    template_config
                )
            
        except Exception as e:
            logger.error(f"创建增强版图表幻灯片失败: {e}")
    
    def _create_conclusion_slide_enhanced(self, slide, slide_content: SlideContent, template_config: TemplateConfig):
        """
        创建增强版结论幻灯片
        
        Args:
            slide: 幻灯片对象
            slide_content: 幻灯片内容
            template_config: 模板配置
        """
        try:
            # 结论幻灯片使用特殊的样式处理
            self._create_content_slide_enhanced(slide, slide_content, template_config)
            
            # 为结论幻灯片添加特殊的装饰元素
            if len(slide_content.content) > 0:
                # 在幻灯片底部添加装饰线条
                line_shape = slide.shapes.add_connector(
                    1,  # 直线连接器
                    Inches(2), Inches(6.8),
                    Inches(8), Inches(6.8)
                )
                
                # 设置线条样式
                line = line_shape.line
                line.color.rgb = RGBColor(*self._hex_to_rgb(template_config.style.color_scheme.accent))
                line.width = Pt(3)
            
        except Exception as e:
            logger.error(f"创建增强版结论幻灯片失败: {e}")
    
    def cleanup_old_files(self, max_age_hours: int = 24):
        """
        清理旧的PPT文件
        
        Args:
            max_age_hours: 文件最大保留时间（小时）
        """
        try:
            current_time = datetime.now()
            
            for filename in os.listdir(self.output_dir):
                if filename.endswith('.pptx'):
                    file_path = os.path.join(self.output_dir, filename)
                    file_time = datetime.fromtimestamp(os.path.getctime(file_path))
                    
                    # 计算文件年龄
                    age_hours = (current_time - file_time).total_seconds() / 3600
                    
                    if age_hours > max_age_hours:
                        os.remove(file_path)
                        logger.info(f"清理旧文件: {filename}")
            
        except Exception as e:
            logger.error(f"清理旧文件失败: {e}")


# 全局PPT生成器实例
ppt_generator = PPTGenerator()